package editorsvg.editor.herramientas;

import editorsvg.editor.cursores.Cursores;
import editorsvg.editor.formas.Elipse;
import editorsvg.editor.herramientas.controles.Cruz;
import editorsvg.editor.herramientas.controles.Flecha;
import editorsvg.editor.vista.EditorDocumento;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;

/**
 * Herramienta para la creación de circulos.
 * @author Jorge Berjano
 */
public class HerramientaElipse2 extends HerramientaBase {

    private EditorDocumento editor;
    private Elipse elipse;
    private Point puntoBase;
    private Point puntoExtremoX;
    private Point puntoExtremoY;
    private Cruz cruz = new Cruz();
    private Flecha flecha = new Flecha();

    private enum Estado {

        ESPERA_CENTRO, ESPERA_RADIO_X, ESPERA_RADIO_Y
    };
    private Estado estado = Estado.ESPERA_CENTRO;

    public HerramientaElipse2(EditorDocumento editor) {
        this.editor = editor;
    }

    @Override
    public boolean pulsado(MouseEvent e) {
        switch (estado) {
            case ESPERA_CENTRO:
                capturarCentro(e.getPoint());
                break;
            case ESPERA_RADIO_X:
                capturarRadioX(e.getPoint());
                break;
            case ESPERA_RADIO_Y:
                capturarRadioY(e.getPoint());
                break;
        }
        return true;
    }

    @Override
    public boolean arrastrando(MouseEvent e) {
        if (estado != Estado.ESPERA_CENTRO) {
            actualizarForma(e.getPoint());
        }
        return true;
    }

    @Override
    public boolean moviendo(MouseEvent e) {
        if (estado != Estado.ESPERA_CENTRO) {
            actualizarForma(e.getPoint());
        }
        return true;
    }

    @Override
    public boolean liberado(MouseEvent e) {

        switch (estado) {
            case ESPERA_CENTRO:
                return false;
            case ESPERA_RADIO_X:
                if (puntoBase.equals(e.getPoint())) {
                    return false;
                }
                capturarRadioX(e.getPoint());
                break;
            case ESPERA_RADIO_Y:
                if (puntoExtremoX.equals(e.getPoint())) {
                    return false;
                }
                capturarRadioY(e.getPoint());
                break;
        }
        return true;
    }

    private void capturarCentro(Point punto) {
        this.elipse = new Elipse();
        puntoBase = punto;
        Point2D.Double centro = editor.getConversor().aUnidadesReales(puntoBase);
        elipse.setCentro(centro);
        estado = Estado.ESPERA_RADIO_X;
    }

    private void capturarRadioX(Point punto) {
        actualizarForma(punto);
        estado = Estado.ESPERA_RADIO_Y;
    }

    private void capturarRadioY(Point punto) {
        actualizarForma(punto);
        editor.finalizarCreacionForma(elipse);
        elipse = null;
        puntoBase = null;
        puntoExtremoX = null;
        puntoExtremoY = null;
        estado = Estado.ESPERA_CENTRO;
    }

    private void actualizarForma(Point puntoActualRaton) {
        Point2D posicion = editor.getConversor().aUnidadesReales(puntoActualRaton);
        if (estado == Estado.ESPERA_RADIO_X) {
            double r = posicion.distance(elipse.getCentro());
            elipse.setRx(r);
            elipse.setRy(r);
            puntoExtremoX = puntoActualRaton;
        } else {
            double ry = Math.abs(posicion.getY() - elipse.getCentro().getY());
            elipse.setRy(ry);
            puntoExtremoY = puntoActualRaton;
        }
        elipse.actualizar();
    }

    @Override
    public Cursor getCursor() {
        return Cursores.ELIPSE.getCursor();
    //return Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
    }

    @Override
    public void pintarEnPixeles(Graphics2D graphics) {
        if (elipse == null) {
            return;
        }
        graphics.setColor(Color.BLACK);
        graphics.setXORMode(Color.WHITE);
        graphics.setStroke(new BasicStroke(1));

        cruz.setPunto(puntoBase);
        cruz.pintar(graphics);
        flecha.setCentro(puntoBase);

        if (puntoExtremoX != null) {
            int rx = editor.getConversor().aPixeles(elipse.getRx());
            flecha.setExtremo(new Point(puntoBase.x + rx, puntoBase.y));
            flecha.pintar(graphics);
        }
        if (puntoExtremoY != null) {
            flecha.setExtremo(new Point(puntoBase.x, puntoExtremoY.y));
            flecha.pintar(graphics);
        }

        Shape formaPixels = editor.getConversor().transformarAPixeles(elipse.getShape());
        graphics.draw(formaPixels);

        graphics.setPaintMode();
    }
}
